package org.movsim.simulator.vehicles.psdecisioncriteria;

import org.movsim.simulator.B5Constants;
import org.movsim.simulator.B5Constants.B5_PSYCOLOGICAL_FACTORS;
import org.movsim.simulator.B5Constants.DRIVER_ACTION;

public class PSBasedDecisionCriteria {
    
    public static double scale(double v) {
        return (v + 1) / 2;
    }

    public static double[] scalePsyclogicalStates(double[] ps) {
        for (B5_PSYCOLOGICAL_FACTORS p : B5_PSYCOLOGICAL_FACTORS.values()) {
            ps[p.ordinal()] = scale(ps[p.ordinal()]);
        }
        return ps;
    }
    
    /*
     * Map driver psychological State on effect of psychological state on action.
     */
    private static double map(DRIVER_ACTION a, double[] ps) {
        ps = scalePsyclogicalStates(ps);
        double retval = 0;
        for (B5_PSYCOLOGICAL_FACTORS p : B5_PSYCOLOGICAL_FACTORS.values()) {
            retval += ps[p.ordinal()] * B5Constants.getB5DriverActionValue(a, p);
        }
        return retval / B5_PSYCOLOGICAL_FACTORS.values().length;
    }
    
    public static boolean respectSpeedLimit(double[] ps) {
        boolean retval = map(DRIVER_ACTION.RESPECT_SPEED_LIMIT, ps) >= 0;
        return retval;
    }

    public static double degreeOfVisibilityOfExitSign(double[] ps) {
        double retval = map(DRIVER_ACTION.VISIBILITY_OF_EXIT_SIGN, ps);
        return retval;
    }

    public static boolean considerLaneChange(double[] ps) {
        boolean retval = map(DRIVER_ACTION.CONSIDER_LANE_CHANGE, ps) >= 0;
        return retval;
    }

    public static boolean checkSafetyCriteriaWhileLaneChange(double[] ps) {
        boolean retval = map(DRIVER_ACTION.SAFETY_CRITERAIA_WHILE_LANE_CHANGE, ps) >= 0;
        return retval;
    }

    public static boolean corporateWithEnteringVehicleByGivingWay(double[] ps) {
        boolean retval = map(DRIVER_ACTION.COOPRATE_WITH_ENTERING_VEHICLE_BY_CHANGING_LANE, ps) >= 0;
        return retval;
    }
    
    public static boolean checkOwnAccelerationSafetyWhileChangingLane(double[] ps) {
        boolean retval = map(DRIVER_ACTION.CHECKS_IS_OWN_ACCELERATION_SAFE_WHILE_CHANGING_LANE, ps) >= 0;
        return retval;
    }

    public static double degreeOfEffectOnAcceleration(double[] ps) {
        double retval = map(DRIVER_ACTION.EFFECT_ON_ACCELERATION, ps);
        return retval;
    }
    
    public static double degreeOfEffectOnDesiredSpeed(double[] ps) {
        double retval = map(DRIVER_ACTION.DESIRED_SPEED_WHICH_EVENTUALLY_EFFECT_ACCELERATION, ps);
        return retval;
    }

    public static boolean considerTrafficLightInAcceleration(double[] ps) {
        boolean retval = map(DRIVER_ACTION.CONSIDER_TRAFFIC_LIGHT_IN_ACCELERATION, ps) >= 0;
        return retval;
    }
    
    public static boolean respectRedLight(double[] ps) {
        boolean retval = map(DRIVER_ACTION.RESPECT_RED_LIGHT, ps) >= 0;
        return retval;
    }

    public static double degreeOfLookAheadDistanceRelatedToSignal(double[] ps) {
        double retval = map(DRIVER_ACTION.LOOK_AHEAD_DISTANCE_INVOLVED_WITH_SIGNAL, ps);
        return retval;
    }

    public static boolean considerExitLaneAcceleration(double[] ps) {
        boolean retval = map(DRIVER_ACTION.CONSIDER_EXIT_LANE_IN_ACCELERATION, ps) >= 0;
        return retval;
    }

    public static double degreeOfEffectOnSpeedAndLongitudinalPosition(double[] ps) {
        double retval = map(DRIVER_ACTION.EFFECT_ON_SPEED_AND_LONGITUDNAL_POSITION, ps);
        return retval;
    }

    public static double degreeOfAcceptableStandstillGap(double[] ps) {
        double retval = map(DRIVER_ACTION.STANDSTILL_GAP, ps);
        return retval;
    }

    public static double degreeOfDistanceBeforeMandatoryChangeLaneForExit(double[] ps) {
        double retval = map(DRIVER_ACTION.DISTANCE_BEFORE_EXIST_MUST_CHANGE_LANE, ps);
        return retval;
    }

    public static boolean checkSpaceBeforePassingTrafficSignal(double[] ps) {
        boolean retval = map(DRIVER_ACTION.CHECK_SPACE_BEFORE_PASSING_TRAFFIC_LIGHT, ps) >= 0;
        return retval;
    }

}
